home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Graphics Plus
/
Graphics Plus.iso
/
msdos
/
raytrace
/
dbwrend
/
source
/
int.c
< prev
next >
Wrap
Text File
|
1989-04-16
|
9KB
|
276 lines
/************************************************************************
* *
* Copyright (c) 1987, David B. Wecker *
* All Rights Reserved *
* *
* This file is part of DBW_Render *
* *
* DBW_Render is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY. No author or distributor accepts *
* responsibility to anyone for the consequences of using it or for *
* whether it serves any particular purpose or works at all, unless *
* he says so in writing. Refer to the DBW_Render General Public *
* License for full details. *
* *
* Everyone is granted permission to copy, modify and redistribute *
* DBW_Render, but only under the conditions described in the *
* DBW_Render General Public License. A copy of this license is *
* supposed to have been given to you along with DBW_Render so you *
* can know your rights and responsibilities. It should be in a file *
* named COPYING. Among other things, the copyright notice and this *
* notice must be preserved on all copies. *
************************************************************************
* *
* Authors: *
* DBW - David B. Wecker *
* *
* Versions: *
* V1.0 870125 DBW - First released version *
* *
************************************************************************/
/* INT.C - calculations for ray intersections with primitives */
#define MODULE_INTER
#include "ray.h"
node *get_next_intersection(which,best_p,best_t)
int which;
vector best_p;
float *best_t;
{
/* This routine returns the pertinent data for the i'th intersection */
if (which >= g_objcounter)
return NULL; /* No more intersections */
else
{
*best_t = g_distances[which];
veccopy(g_points[which],best_p);
return g_objpairs[which];
}
}
void add_intersection(np,p,t,attenuating)
node *np;
vector p;
float t;
int attenuating;
{
int add;
/*
* This routine adds the passed intersection information to the global list
* of intersections. As a performance optimization,if we know that all
* objects are opaque,then rather than accumulating the entire list and
* sorting it later,we merely keep track of the closest intersection.
*/
add = FALSE;
if ( allopaque == 0 || /* Some transparency, all everything */
g_objcounter == 0 || /* First opaque intersection */
t < g_distances[0])
{
add = TRUE; /* Nearer opaque intersection */
}
if ( attenuating &&
np->attr.tra[0] >= .99 &&
np->attr.tra[1] >= .99 &&
np->attr.tra[2] >= .99)
{
add = FALSE; /* ignore invisible objects when doing shadows */
}
if (add)
{
g_distances[g_objcounter] = t;
veccopy(p,g_points[g_objcounter]);
g_objpairs[g_objcounter] = np;
if (g_objcounter < MAXOBJ)
g_objcounter++;
}
}
void calc_intersections(np,eye,d,attenuating)
node *np; /* current node */
vector d; /* direction vector for current ray */
vector eye; /* current ray origin (eye point) */
int attenuating; /* attenuation factor for each hit */
{
/*
* This routine calculates the intersection of a ray with a given object.
* If an intersection is found,the appropriate parameters are added to a
* global list. This routine is recursive,to handle nested extents.
*/
vector p;
float t;
int hit;
long curs;
/* keep track of maximum stack extent */
curs = curstack();
if (curs < stackbot)
stackbot = curs;
while (np)
{
hit = FALSE;
switch (np->kind)
{
case EXTENT :
if (hitsphere(eptr(np)->center,eptr(np)->radius,eye,d,p,&t))
calc_intersections(eptr(np)->sub,eye,d,attenuating);
break;
case SPHERE :
hit = hitsphere(sptr(np)->center,sptr(np)->radius,eye,d,p,&t);
break;
case TRIANGLE :
hit = hittriangle(np,eye,d,p,&t);
break;
case QUAD :
hit = hitquad(np,eye,d,p,&t);
break;
case RING :
hit = hitring(np,eye,d,p,&t);
break;
case CYLINDER :
hit = hitcylinder(np,eye,d,p,&t);
break;
default :
hit = FALSE;
break;
}
if (hit)
add_intersection(np,p,t,attenuating); /* Add to global list */
np = np->next; /* On to the next object */
}
}
void all_intersects(eye,d,attenuating)
vector d;
vector eye;
int attenuating;
{
/*
* This routine computes all of the ray-object intersections that occur for
* the specified ray. The intersections are stored in global arrays, sorted
* closest intersection to furthest.
*/
g_objcounter = 0; /* Clear the intersection list */
calc_intersections(root,eye,d,attenuating); /* Find them & add to list */
if (g_objcounter > 1)
shell(g_distances,g_points,g_objpairs,g_objcounter); /* Sort them */
/* Keep statistics (and decide when to GIVE UP!!) */
if (++curr_runs >= max_runs)
longjmp(env,-1);
if (g_objcounter > max_intersects)
max_intersects = g_objcounter;
}
int bouncelighting(pseudointensity,pseudolitdir,bouncenp,lit)
vector pseudointensity,
pseudolitdir;
node *bouncenp;
int lit;
{
vector n,bouncepoint,lightdir;
if (bouncenp->kind == SPHERE || bouncenp->attr.ref == 0.0)
return FALSE; /* No pseudo light source from here */
else
{
switch (bouncenp->kind)
{
case TRIANGLE :
veccopy(tptr(bouncenp)->position,bouncepoint);
break;
case QUAD :
veccopy(qptr(bouncenp)->position,bouncepoint);
break;
case RING :
veccopy(rptr(bouncenp)->position,bouncepoint);
break;
}
findnormal(bouncenp,bouncepoint,n);
veccopy(light[lit].direction,lightdir); /* Assume directional light */
if (light[lit].kind != 0)
{ /* Point source */
DIRECTION(bouncepoint,lightdir,lightdir);
}
vecscale(2.0 * DOT(lightdir,n),n,pseudolitdir);
vecsub(lightdir,pseudolitdir,pseudolitdir);
vecscale(bouncenp->attr.ref,light[lit].intensity,pseudointensity);
return TRUE;
}
}
void blendcolor(original,target,scale,result)
vector original;
vector target;
vector result;
float scale;
{
vector path;
if (scale < 0.0)
scale = 0.0; /* clip off excessive blending */
if (scale > 1.0)
scale = 1.0;
vecsub(target,original,path);
vecscale(scale,path,path);
vecsum(original,path,result);
}
void getatten(atten,p,d,lit,pointdist)
vector atten;
vector p;
vector d;
int lit;
float pointdist;
{
vector best_p;
float best_t;
int hitnext;
#ifdef MCH_AMIGA
node *occlude = 1L;
#else
node *occlude = (node *)1L;
#endif
atten[0] = 1.0; /* assume no attenuation */
atten[1] = 1.0;
atten[2] = 1.0;
hitnext = 0;
all_intersects(p,d,1); /* Compute all intersections */
while (occlude && (atten[0] > 0.01 || atten[1] > 0.01 || atten[2] > 0.01))
if (occlude = get_next_intersection(hitnext,best_p,&best_t))
{
if (light[lit].kind == 0 || best_t <= pointdist)
{
vecmul(atten,occlude->attr.tra,atten);
}
hitnext++;
}
}